;; generic/random.scm - (c) rohan drape, 2000-2005

;; Random <real>s.  A generic that evaluates to a random value with a
;; distribution determined by `random-normal-value'.  Applied to no
;; arguments the result will be in [0,1].  Applied to a number the
;; result will be in [0,`a').  Applied to two numbers the result will
;; be in [a,b).  Applied to a proper list or vector or string the
;; result is a randomly selected element of the sequence.

(define-generic randomF)
(define-method (randomF) (randomN))
(define-method (randomF (n <Num>)) (random-zero-right n))
(define-method (randomF (l <Num>) (r <Num>)) (random-left-right l r))

;; Random <integer>s.  A generic that evaluates to a random integer
;; value with a distribution determined by `random-normal-value'.
;; Applied to a number the result will be in [0,a).  Applied to two
;; numbers the result will be in [a,b).

(define-generic randomI)
(define-method (randomI (n <Int>)) (randomI-zero-right n))
(define-method (randomI (l <Int>) (r <Int>)) (randomI-left-right l r))

;; Random element selection

(define-generic randomC)
(define-method (randomC (l <List>)) (choose l))
(define-method (randomC (l <List>) (p <List>)) (choose/proportions l p))
(define-method (randomC (v <Vector>)) (vector-choose v))  
(define-method (randomC (s <String>)) (string-choose s))  

;; Random collections.

(define (randomF-list n . data) (tabulate n (lambda (i) (apply randomF data))))
(define (randomI-list n . data) (tabulate n (lambda (index) (apply randomI data))))
(define (randomF-vector n . data) (list->vector (apply randomF-list n data)))
(define (randomF-stream . args) (stream-cons (apply randomF args) (apply randomF-stream args)))

;; Idiom over 'random'.  Evaluates to a no-argument procedure that
;; will generate a random value according to `d'.

(define (randomF-procedure . args) (lambda () (apply randomF args)))

;; A variant of 'randomF' that parameterizes 'random-normal' with
;; `normal'.

(define (randomF* normal . arguments)
  (parameterize
   ((randomN_ normal))
   (apply randomF arguments)))
